package common.library.utils;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;

import java.util.Hashtable;

import common.library.activities.ScanQrActivity;
import common.library.models.StringCallback;
import lombok.var;

public class QrUtil {

    static Hashtable<EncodeHintType, String> encodeHints;
    static Hashtable<DecodeHintType, String> decodeHints;

    static {
        encodeHints = new Hashtable();
        encodeHints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 字符转码格式设置
        encodeHints.put(EncodeHintType.ERROR_CORRECTION, "H"); // 容错级别设置 默认为L
        encodeHints.put(EncodeHintType.MARGIN, "4"); // 空白边距设置

        decodeHints = new Hashtable();
        decodeHints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 字符转码格式设置
    }

    public static Bitmap create(String content) throws Exception {
        int size = 240;
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, size, size, encodeHints);
        int[] pixels = new int[size * size];
        for (int y = 0; y < size; y++) {
            for (int x = 0; x < size; x++) {
                if (bitMatrix.get(x, y)) {
                    // 黑色色块像素设置
                    pixels[y * size + x] = 1;
                } else {
                    // 白色色块像素设置
                    pixels[y * size + x] = 0;
                }
            }
        }
        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, size, 0, 0, size, size);
        return bitmap;
    }

    static class BitmapLuminanceSource extends LuminanceSource {

        private final byte[] bitmapPixels;

        public BitmapLuminanceSource(Bitmap bitmap) {
            super(bitmap.getWidth(), bitmap.getHeight());

            // 首先，要取得该图片的像素数组内容
            int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
            this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
            bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());

            // 将int数组转换为byte数组，也就是取像素值中蓝色值部分作为辨析内容
            for (int i = 0; i < data.length; i++) {
                this.bitmapPixels[i] = (byte) data[i];
            }
        }

        @Override
        public byte[] getMatrix() {
            // 返回我们生成好的像素数据
            return bitmapPixels;
        }

        @Override
        public byte[] getRow(int y, byte[] row) {
            // 这里要得到指定行的像素数据
            System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());
            return row;
        }
    }

    public static String decode(Bitmap bitmap) {
        try {
            var result = new QRCodeReader().decode(new BinaryBitmap(new HybridBinarizer(new BitmapLuminanceSource(bitmap))), decodeHints).getText();
            //LogUtil.info("二维码识别成功：" + result);
            return result;
        } catch (Exception ex) {
            //ex.printStackTrace();
            //LogUtil.info("无效二维码");
            return null;
        }
    }

    public static String superDecode(Bitmap bitmap) {
        bitmap = ImageUtil.gray(bitmap);
        var result = decode(bitmap);
        //30%-100%
        for (var index = 30; index < 100; index += 3) {
            if (result == null) {
                result = decode(ImageUtil.cut(bitmap, 0.01f * index, true));
                if (result != null) {
                    LogUtil.info("superDecode 二维码识别成功： index=" + index);
                    break;
                }
            }
        }
        return result;
    }

    public static String decode(String path) {
        var bitmap = ImageUtil.get(path);
        return decode(bitmap);
    }

    public static void scan(Activity activity, StringCallback callback) {
        ScanQrActivity.callback = callback;
        var intent = new Intent(activity, ScanQrActivity.class);
        activity.startActivity(intent);
    }
}
